#include <zephyr/devicetree.h>
#include <zephyr/drivers/gpio.h>
#include <zephyr/kernel.h>
#include <zephyr/logging/log.h>
#include <zephyr/logging/log_ctrl.h>
#include <zephyr/pm/device.h>
#include <zephyr/storage/flash_map.h>

#include "expower.h"
#include "spi_flash_mx35.h"

LOG_MODULE_REGISTER(main, LOG_LEVEL_DBG);

static void spi_test_thread(void)
{
    uint32_t addr = 0;
    uint32_t counter = 0;
    int ret;
    uint8_t jedec_id[2] = { 0 };
    uint32_t start_addr = 0;
    uint32_t end_addr = 268435456;
    uint32_t offset_addr = 0;
    uint8_t rbuf[16] = { 0 };
    uint8_t wbuf[16] = { 0 };

    const struct device *flash_dev = DEVICE_DT_GET(DT_NODELABEL(mx35lf2g14ac));
    size_t page_count;
    uint8_t state = 0;

    do {
        for (int i = 0; i < sizeof(wbuf); i++) {
            wbuf[i] = counter;
        }
        counter++;

        state = mx35_flash_get_state(flash_dev);
        printk("flash state: %d\n", state);

        struct mx35_flash_parameters *params = mx35_flash_get_parameters(flash_dev);
        printk("chip ID: %02X%02X\n", params->jedec_id[0], params->jedec_id[1]);
        printk("chip_size: %d\n", params->chip_size);
        printk("block_size: %d\n", params->block_size);
        printk("page_size: %d\n", params->page_size);
        printk("page_oob_size: %d\n", params->page_oob_size);

        printk("read/write addr: %d\n", addr);
        ret = mx35_flash_read(flash_dev, addr, rbuf, sizeof(rbuf));
        if (ret) {
            LOG_ERR("flash read/write error, %d", __LINE__);
        }
        LOG_HEXDUMP_INF(rbuf, sizeof(rbuf), "Read");

        ret = mx35_flash_write(flash_dev, addr, wbuf, sizeof(wbuf));
        if (ret) {
            LOG_ERR("flash read/write error, %d", __LINE__);
        }
        LOG_HEXDUMP_INF(wbuf, sizeof(wbuf), "Write");

        ret = mx35_flash_read(flash_dev, addr, rbuf, sizeof(rbuf));
        if (ret) {
            LOG_ERR("flash read/write error, %d", __LINE__);
        }
        LOG_HEXDUMP_INF(rbuf, sizeof(rbuf), "Write confirm");

        addr += 16;
        k_sleep(K_MSEC(100));
    } while (addr < end_addr);

    if (ret)
        LOG_ERR("flash test failed.");
    else
        LOG_WRN("flash test OK.");
}

#define MY_DRIVER_A "my_driver_A"

int main(void)
{
    printk("start flash test task.\n");

    const struct device *dev = DEVICE_DT_GET(DT_NODELABEL(expwrctrl));
    if (!dev) {
        LOG_ERR(" DEVICE NOT FOUND: %d", __LINE__);
    }

    spi_test_thread();

    // printk("expower state: %d\n", expwrctrl_inst->api->get(dev));
    // expwrctrl_inst->api->set(dev, 1);

    return 0;
}
